package com.bowlong.util;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class MultiKey2 {

	private final Object[] keys;
	private transient int hashCode;

	public MultiKey2(final Object key1) {
		this((Object[]) new Object[] { key1 }, false);
	}

	public MultiKey2(final Object key1, final Object key2) {
		this((Object[]) new Object[] { key1, key2 }, false);
	}

	public MultiKey2(final Object key1, final Object key2, final Object key3) {
		this((Object[]) new Object[] { key1, key2, key3 }, false);
	}

	public MultiKey2(final Object key1, final Object key2, final Object key3,
			final Object key4) {
		this((Object[]) new Object[] { key1, key2, key3, key4 }, false);
	}

	public MultiKey2(final Object key1, final Object key2, final Object key3,
			final Object key4, final Object key5) {
		this((Object[]) new Object[] { key1, key2, key3, key4, key5 }, false);
	}

	public MultiKey2(final Object key1, final Object key2, final Object key3,
			final Object key4, final Object key5, final Object key6) {
		this((Object[]) new Object[] { key1, key2, key3, key4, key5, key6 },
				false);
	}

	public MultiKey2(final Object key1, final Object key2, final Object key3,
			final Object key4, final Object key5, final Object key6,
			final Object key7) {
		this(
				(Object[]) new Object[] { key1, key2, key3, key4, key5, key6,
						key7 }, false);
	}

	public MultiKey2(final Object key1, final Object key2, final Object key3,
			final Object key4, final Object key5, final Object key6,
			final Object key7, final Object key8) {
		this((Object[]) new Object[] { key1, key2, key3, key4, key5, key6,
				key7, key8 }, false);
	}

	public MultiKey2(final Object[] keys) {
		this(keys, true);
	}

	public MultiKey2(final Object[] keys, final boolean makeClone) {
		super();
		if (keys == null) {
			throw new IllegalArgumentException(
					"The array of keys must not be null");
		}
		if (makeClone) {
			this.keys = keys.clone();
		} else {
			this.keys = keys;
		}

		calculateHashCode(keys);
	}

	public Object[] getKeys() {
		return keys.clone();
	}

	public Object getKey(final int index) {
		return keys[index];
	}

	public int size() {
		return keys.length;
	}

	@Override
	public boolean equals(final Object other) {
		if (other == this) {
			return true;
		}
		if (other instanceof MultiKey2) {
			final MultiKey2 otherMulti = (MultiKey2) other;
			return Arrays.equals(keys, otherMulti.keys);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return hashCode;
	}

	@Override
	public String toString() {
		return "MultiKey" + Arrays.toString(keys);
	}

	private void calculateHashCode(final Object[] keys) {
		// int total = 0;
		// for (final Object key : keys) {
		// if (key != null) {
		// total ^= key.hashCode();
		// }
		// }
		// hashCode = total;
		hashCode = calcHashCode(keys);
	}

	public static int calcHashCode(final Object... keys) {
		String skey = Arrays.toString(keys);
		return skey.hashCode();
	}

	private Object readResolve() {
		calculateHashCode(keys);
		return this;
	}

	public static void main(String[] args) {
		Map<MultiKey2, String> map = new HashMap<>();
		MultiKey2 multiKey = new MultiKey2(1, 1);
		map.put(multiKey, "localizedText x");

		// later retireve the localized text
		MultiKey2 multiKey2 = new MultiKey2(1, 1);
		String localizedText = (String) map.get(multiKey2);

		System.out.println(localizedText);
	}
}
